//===--- Passes/CallGraph.cpp ---------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//===----------------------------------------------------------------------===//

#include "callgraph.h"
namespace hfsort {

bool MyCallGraph::addFunc(
  std::string name,
  uint64_t addr,
  uint32_t size,
  uint32_t group
) {
  if (name.empty()) return false;
  auto it = addr2TargetId.find(addr);
  if (it != addr2TargetId.end()) {
    auto& base = funcs[it->second];
    auto& baseTarget = targets[it->second];
    base.mangledNames.push_back(name);
    // Store the same id for different symbol name with same start address
    func2TargetId[name] = it->second;
    if (size > baseTarget.size) baseTarget.size = size;
    majin_debug("Func: adding '%s' to (%u)\n", name.c_str(), it->second);
    return true;
  }
  auto id = addTarget(size);
  funcs.emplace_back(name, addr, group);
  func2TargetId[name] = id;
  addr2TargetId[addr] = id;
  majin_debug("Func: adding (%u): %016lx %s %u\n", id, (long)addr, name.c_str(),
          size);
  return true;
}

TargetId MyCallGraph::addrToTargetId(uint64_t addr) const {
  auto it = addr2TargetId.upper_bound(addr);
  if (it == addr2TargetId.begin()) return InvalidId;
  --it;
  const auto &f = funcs[it->second];
  const auto &fTarget = targets[it->second];
  assert(f.addr <= addr);
  if (f.addr + fTarget.size <= addr) {
    return InvalidId;
  }
  return it->second;
}

TargetId MyCallGraph::funcToTargetId(const std::string &func) const {
  auto it = func2TargetId.find(func);
  if (it != func2TargetId.end()) {
    return it->second;
  }
  return InvalidId;
}

} // namespace hfsort